package online

import (
	"errors"
	"server/common"

	"github.com/mitchellh/mapstructure"
	"github.com/sirupsen/logrus"
)

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) checkStartSubscribeReqData(data common.P2PStartSubscribeReqData) error {
	// Check if call ID provided
	if data.CallId == "" {
		return errors.New("call_id cannot be empty in StartSubscribeReq")
	}

	// Check if user ID provided
	if data.UserId == "" {
		return errors.New("user_id cannot be empty in StartSubscribeReq")
	}

	// Check if pub user ID provided
	if data.PubUserId == "" {
		return errors.New("pub_user_id cannot be empty in StartSubscribeReq")
	}

	// Check if media info provided
	if data.Media.MediaId == "" {
		return errors.New("media_id cannot be empty in StartSubscribeReq")
	}

	// Check if call exists
	if !s.callMgr.CallExists(data.CallId) {
		return errors.New("call does not exist in StartSubscribeReq")
	}

	// Check if user exists
	if !s.userMgr.UserExists(data.UserId) {
		return errors.New("user does not exist in StartSubscribeReq")
	}

	// Check if pub user exists
	if !s.userMgr.UserExists(data.PubUserId) {
		return errors.New("pub_user_id does not exist in StartSubscribeReq")
	}

	// Check if media exists
	if !s.callMgr.HasPublishMedia(data.CallId, data.PubUserId, data.Media) {
		return errors.New("media does not exist in StartSubscribeReq")
	}

	return nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) sendStartSubscribeRes(rid string, reqData common.P2PStartSubscribeReqData,
	code int, msg string, connId string) {

	resMsg := common.Message{
		Cmd: common.P2P_START_SUBSCRIBE_RES,
		Rid: rid,
		Data: common.ResMsgData{
			Code: code,
			Msg:  msg,
			Data: common.P2PStartSubscribeResData{
				CallId:    reqData.CallId,
				Media:     reqData.Media,
				UserId:    reqData.UserId,
				PubUserId: reqData.PubUserId,
			},
		},
	}

	s.dispatcher.Dispatch(resMsg, s.serviceInfo, common.AccessServiceInfo, connId)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func (s *OnlineService) handleStartSubscribeReq(msg common.Message, from common.ServiceInfo,
	connId string) error {
	common.Logger(common.SERVICE_TYPE_ONLINE, msg.Rid).WithFields(logrus.Fields{
		"msg":    common.ToJson(msg),
		"from":   from,
		"connId": connId,
	}).Info("call handleStartSubscribeReq")

	var reqData common.P2PStartSubscribeReqData
	if err := mapstructure.Decode(msg.Data, &reqData); err != nil {
		s.sendStartSubscribeRes(msg.Rid, reqData, 1, err.Error(), connId)
		return nil
	}

	if err := s.checkStartSubscribeReqData(reqData); err != nil {
		s.sendStartSubscribeRes(msg.Rid, reqData, 1, err.Error(), connId)
		return nil
	}

	peerUserId, err := s.callMgr.GetPeerUserId(reqData.CallId, reqData.UserId)
	if err != nil {
		s.sendStartSubscribeRes(msg.Rid, reqData, 1, "failed to get peer userId", connId)
		return nil
	}

	peerUser := s.userMgr.GetUserByUserId(peerUserId)
	if peerUser == nil {
		s.sendStartSubscribeRes(msg.Rid, reqData, 5, "peer user not found", connId)
		return nil
	}

	// Send start subscribe response to the requester
	s.sendStartSubscribeRes(msg.Rid, reqData, 0, "success", connId)

	// Notify the peer user to start producing media
	notify := common.Message{
		Cmd: common.P2P_START_PRODUCE_NOTIFY,
		Rid: msg.Rid,
		Data: common.P2PStartProduceNotifyData{
			CallId: reqData.CallId,
			Media:  reqData.Media,
		},
	}
	s.dispatcher.Dispatch(notify, s.serviceInfo, common.AccessServiceInfo, peerUser.ConnId)

	return nil
}
